package com.demo.service.impl;

import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.demo.constant.Constant;
import com.demo.entity.Department;
import com.demo.entity.Patient;
import com.demo.entity.Vo.PatientIPCVO;
import com.demo.entity.Vo.VtePreventiveDoctorAdviceVo;
import com.demo.entity.VtePreventive;
import com.demo.entity.VtePreventiveDoctorAdvice;
import com.demo.enums.PhysicalPreventionIpcFreEnum;
import com.demo.enums.PreventiveDoctorAdviceStatusEnum;
import com.demo.mapper.*;
import com.demo.response.Result;
import com.demo.service.IUserService;
import com.demo.service.IVtePreventiveDoctorAdviceService;
import com.demo.websocket.response.entity.PatientAdvice;
import com.demo.websocket.vo.IpcDoctorAdvice;
import com.demo.websocket.vo.VteIpcMessageVO;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.validation.constraints.NotBlank;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * vte预防处置医嘱 服务实现类
 *
 * @author zm
 * @since 2020-11-27
 */
@Slf4j
@Service
public class VtePreventiveDoctorAdviceServiceImpl extends ServiceImpl<VtePreventiveDoctorAdviceMapper, VtePreventiveDoctorAdvice> implements IVtePreventiveDoctorAdviceService {
    @Resource
    VtePreventiveDoctorAdviceMapper doctorAdviceMapper;
    @Resource
    PatientMapper patientMapper;
    @Resource
    IUserService userService;
    @Resource
    VtePreventiveMapper vtePreventiveMapper;
    @Resource
    DepartmentMapper departmentMapper;
    @Resource
    PhysicalPreventionLogMapper physicalPreventionLogMapper;

    /**
     * 防治医嘱更新
     *
     * @param doctorAdvice 医嘱对象
     * @return
     */
    @Override
    public Result invalidDoctorAdvice(VtePreventiveDoctorAdvice doctorAdvice) throws Exception {
        if (doctorAdvice.getDoctorAdviceId() == null || doctorAdvice.getUpdatedUserId() == null) {
            return Result.error(Constant.KEY_ID);
        }

        //停止医嘱
        if (doctorAdvice.getStopedUserId() != null) {
            VtePreventiveDoctorAdvice advice = doctorAdviceMapper.selectById(doctorAdvice.getDoctorAdviceId());
            if (advice.getStatus().equals(2)) {
                throw new Exception("操作失败，该医嘱已停止");
            }
            doctorAdvice.setStopedUserTime(new Date());
        }

        //作废医嘱
        if (doctorAdvice.getDeletedUserId() != null) {
            VtePreventiveDoctorAdvice advice = doctorAdviceMapper.selectById(doctorAdvice.getDoctorAdviceId());
            if (advice.getDeletedUserId() != null) {
                throw new Exception("操作失败，该医嘱已作废");
            }
            doctorAdvice.setDeletedTime(new Date());
        }

        updateById(doctorAdvice);
        return Result.success();
    }

    /**
     * 防治医嘱列表
     *
     * @param pageNumber     页码
     * @param pageSize       每页数量
     * @param adviseType     医嘱类型  1药物 2物理
     * @param patientId      病患序列号【ID】
     * @param status         医嘱状态 0默认全部   1.未停止  2.已停止
     * @param validityLength 医嘱时限 0默认全部   1.长期    2.临时
     * @return
     */
    @Override
    public Result doctorAdviceList(Integer pageNumber, Integer pageSize, Integer patientId, Integer adviseType, Integer status, Integer validityLength) {
        //通过病患ID序列号，获取病患vet诊断评估序列号
        List<Integer> vteIds = patientMapper.getVteIDByPatientId(patientId);

        //构造条件
        IPage<VtePreventiveDoctorAdvice> page = new Page<>(pageNumber, pageSize);
        QueryWrapper<VtePreventiveDoctorAdvice> queryWrapper = new QueryWrapper<>();
        if (vteIds.size() != 0) {
            queryWrapper.in("vte_preventive_id", vteIds);
        }

        queryWrapper.eq(adviseType != null, "advise_type", adviseType);
        queryWrapper.eq(status != null, "status", status);
        queryWrapper.eq(validityLength != null, "validity_length", validityLength);
        queryWrapper.orderByDesc("created_time");
        page = doctorAdviceMapper.selectPage(page, queryWrapper);
        List<VtePreventiveDoctorAdvice> list = page.getRecords();

        List<VtePreventiveDoctorAdviceVo> adviceVoList = new ArrayList<>();
        for (VtePreventiveDoctorAdvice advice : list) {
            VtePreventiveDoctorAdviceVo adviceVo = new VtePreventiveDoctorAdviceVo();
            BeanUtils.copyProperties(advice, adviceVo);
            adviceVo.setCreatUserName(userService.getUnameById(advice.getCreatedUserId()));
            if (advice.getStopedUserId() != null) {
                adviceVo.setStopedUserName(userService.getUnameById(advice.getStopedUserId()));
            }
            adviceVoList.add(adviceVo);
        }
        PageInfo<VtePreventiveDoctorAdviceVo> pageInfo = new PageInfo<>(adviceVoList);
        pageInfo.setTotal(page.getTotal());
        pageInfo.setPages((int) page.getPages());
        if (pageNumber.equals(page.getPages())) {
            pageInfo.setIsLastPage(false);
        } else {
            pageInfo.setIsLastPage(true);
        }
        return Result.success(pageInfo);
    }

    /**
     * 防治医嘱列表 --2
     *
     * @param pageNumber
     * @param pageSize
     * @param patientId
     * @return
     */
    @Override
    public Result doctorAdviceListTwo(Integer pageNumber, Integer pageSize, Integer patientId, Integer adviseType, Integer status, Integer validityLength) {
        //最后返回对象
        PageHelper.startPage(pageNumber, pageSize);
        List<VtePreventiveDoctorAdviceVo> list = doctorAdviceMapper.getDoctorAdvice(pageNumber, pageSize, patientId, adviseType, status, validityLength);
        PageInfo<VtePreventiveDoctorAdviceVo> pageInfo = new PageInfo<>(list);
        return Result.success(pageInfo);
    }

    /**
     * 新增医嘱
     *
     * @param doctorAdvice
     * @return
     */
    @Override
    public boolean addDoctorAdvice(VtePreventiveDoctorAdvice doctorAdvice) {
        return save(doctorAdvice);
    }

    /*
     * @Author 李洋
     * @Date 2021-04-08 3:52 AM
     * @Description 功能描述:根据病区ID获取IPC医嘱
     * @Param
     * @Return
     * @Since version-1.0
     */
    @Override
    public Result doctorIpcAdviceByWardId(Integer pageNumber, Integer pageSize, String wardId) {
        Integer offsetNumber = (pageNumber - 1) * pageSize;
        List<PatientIPCVO> list = doctorAdviceMapper.getDoctorIpcAdviceByWardId(wardId, pageSize, offsetNumber);
        for (PatientIPCVO item : list) {
            JSONObject object = JSONUtil.parseObj(item.getPara());
            Object stringMap = object.get("物理预防");
            JSONObject parseObj = JSONUtil.parseObj(stringMap);
            item.setPara(parseObj.get("para").toString());
        }
        return Result.success(list);
    }

    /*
     * @Author 李洋
     * @Date 2021-04-08 3:52 AM
     * @Description 功能描述:根据IPC物理医嘱更新
     * @Param
     * @Return
     * @Since version-1.0
     */
    @Override
    public Result doctorIpcAdviceUpdate(Integer vte_preventive_id, Integer physical_prevention) {
        IPage<VtePreventive> page = new Page<>(1, 10);
        QueryWrapper<VtePreventive> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("vte_preventive_id", vte_preventive_id);
        page = vtePreventiveMapper.selectPage(page, queryWrapper);
        if (page.getRecords().isEmpty()) {
            return Result.error("医嘱不存在");
        } else {
            UpdateWrapper updateWrapper = new UpdateWrapper();
            updateWrapper.eq("vte_preventive_id", vte_preventive_id);

            VtePreventive vtePreventive = new VtePreventive();
            vtePreventive.setPhysicalPrevention(physical_prevention);
            vtePreventiveMapper.update(vtePreventive, updateWrapper);
            return Result.success();
        }
    }

    @Override
    public void updateVtePreventiveAdviceInfoByKey(Integer doctorAdviceId, String updateKey, String updateValue) {
        UpdateWrapper<VtePreventiveDoctorAdvice> updateWrapper = new UpdateWrapper();
        updateWrapper.set(updateKey, updateValue);
        updateWrapper.eq("doctor_advice_id", doctorAdviceId);
        doctorAdviceMapper.update(null, updateWrapper);
    }

    @Override
    public Result getVtePreventiveAdviceInfoByKey(Integer doctorAdviceId, Integer patientId, Integer adviseType, String getKey) {
        QueryWrapper<VtePreventiveDoctorAdvice> vtePreventiveDoctorAdviceQueryWrapper = new QueryWrapper();
        if (doctorAdviceId != null) {
            vtePreventiveDoctorAdviceQueryWrapper.eq("doctor_advice_id", doctorAdviceId);
        } else if (patientId != null) {
            vtePreventiveDoctorAdviceQueryWrapper.eq("patient_id", patientId);
            vtePreventiveDoctorAdviceQueryWrapper.eq("status", PreventiveDoctorAdviceStatusEnum.UN_STOP.getValue());
            vtePreventiveDoctorAdviceQueryWrapper.isNull("deleted_time");
            vtePreventiveDoctorAdviceQueryWrapper.eq("advise_type", adviseType);
        }
        vtePreventiveDoctorAdviceQueryWrapper.select(new String[]{getKey});
        VtePreventiveDoctorAdvice vtePreventiveDoctorAdvice = doctorAdviceMapper.selectOne(vtePreventiveDoctorAdviceQueryWrapper);
        return Result.success(vtePreventiveDoctorAdvice);
    }

    public Result getMedicinePreventiveInterval(String wayGap) throws Exception {
        List<VtePreventiveDoctorAdvice> medicineList = null;
        if (wayGap != null)
            try {
                QueryWrapper<VtePreventiveDoctorAdvice> vtePreventiveDoctorAdviceQueryWrapper = new QueryWrapper();
                vtePreventiveDoctorAdviceQueryWrapper.select(new String[]{"vte_preventive_id,patient_id"});
                vtePreventiveDoctorAdviceQueryWrapper.isNotNull("deleted_time");
                vtePreventiveDoctorAdviceQueryWrapper.eq("status", PreventiveDoctorAdviceStatusEnum.UN_STOP.getValue());
                vtePreventiveDoctorAdviceQueryWrapper.eq("way_gap", wayGap);
                medicineList = doctorAdviceMapper.selectList(vtePreventiveDoctorAdviceQueryWrapper);
                for (VtePreventiveDoctorAdvice vtePreventiveDoctorAdvice : medicineList) ;
            } catch (Exception e) {
                log.error("定时消息错误{}", e);
            }
        return Result.success(medicineList);
    }

    @Override
    public Result getVteAdviceDeptSnRanking(String orderType, Integer topNumber) {
        return Result.success(doctorAdviceMapper.getVteAdviceDeptSnRanking(orderType, topNumber));
    }

    @Override
    public com.demo.websocket.response.Result getIPCDoctorAdvice(VteIpcMessageVO vteIpc) {
        List<PatientAdvice> patientAdvices = new ArrayList<>();
        try {
            Department department = departmentMapper.getdeptMapping(Integer.parseInt(vteIpc.getPatWard()));
            if (department == null) {
                log.info(String.format("当前病区[%s]对应的部门为空", vteIpc.getPatWard()));
            }
            List<Patient> patients = patientMapper.selectByDeptSn(department.getDeptSn());
            if (patients != null && patients.size() > 0) {
                List<Integer> patientIds = patients.stream().map(Patient::getPatientId).collect(Collectors.toList());
                Integer pageSize = 5;
                Integer offsetNumber = (vteIpc.getPage() == null ? 0 : vteIpc.getPage() - 1)  * pageSize;
                List<IpcDoctorAdvice> advices = doctorAdviceMapper.selectAdviceByPatients(patientIds, pageSize, offsetNumber);
                log.info("分页 IPC 医嘱数据 data={}", JSON.toJSONString(advices));
                for (IpcDoctorAdvice advice : advices) {
                    PatientAdvice patientAdvice = new PatientAdvice();
                    patientAdvice.setId(String.valueOf(advice.getPatientId()));
                    patientAdvice.setBed(String.format("%s-0", advice.getBedId()));
                    patientAdvice.setWard(String.valueOf(advice.getWardId()));
                    patientAdvice.setAdv(String.valueOf(advice.getDoctorAdviceId()));
                    patientAdvice.setPara("40LE06080070060120080070060120");//设置默认值
                    try {
                        JSONObject adviseContent = JSONUtil.parseObj(advice.getAdviseContent());
                        if (adviseContent.containsKey("物理预防")) {
                            // 处理 para
                            String para = adviseContent.getJSONObject("物理预防").getStr("para");
                            if (!Objects.equals(para, "")) {
                                patientAdvice.setPara(para);
                            }

                            // 处理剩余执行次数
                            String ipcFre = adviseContent.getJSONObject("物理预防").getStr("ipc_fre");
                            PhysicalPreventionIpcFreEnum ipcFreEnum = PhysicalPreventionIpcFreEnum.getByName(ipcFre);
                            if (ipcFreEnum != null) {
                                // 查询当前医嘱已执行次数
                                Integer alreadyExecuteCount = physicalPreventionLogMapper.queryByVtePreventiveId(advice.getDoctorAdviceId());
                                Integer remainExecuteCount = ipcFreEnum.getValue() - alreadyExecuteCount;
                                if (remainExecuteCount > 0) {
                                    patientAdvice.setBed(String.format("%s-%s", advice.getBedId(), remainExecuteCount));
                                }
                            }
                        }
                    } catch (Exception e) {
                        log.info("解析 AdviseContent 异常，para 保持为空返回", e);
                    }
                    patientAdvices.add(patientAdvice);
                }
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        // 分页返回
        return new com.demo.websocket.response.Result(200, "查询成功", vteIpc.getPage(), (new Date()).getTime(), patientAdvices);
    }

    @Override
    public Result updateDoctorAdvicePara(Integer doctorAdviceId, String para) {
        VtePreventiveDoctorAdvice advice = doctorAdviceMapper.selectById(doctorAdviceId);
        if (advice == null) {
            return Result.error("医嘱不存在");
        }
        try {
            JSONObject adviseContent = JSONUtil.parseObj(advice.getAdviseCotent());
            if (adviseContent.containsKey("物理预防")) {
                adviseContent.getJSONObject("物理预防").putOpt("para", para);
                advice.setAdviseCotent(JSON.toJSONString(adviseContent));
                doctorAdviceMapper.updateById(advice);
            }
        } catch (Exception e) {
            log.info("解析 AdviseContent 异常，para 保持为空返回");
        }
        return Result.success();
    }

}
